<template>
  <div class="goods-sku">
    <dl v-for="(item,index) in specs" :key="index">
      <dt>{{item.name}}</dt>
      <dd>
        <template v-for="(tag,i) in item.values" :key="i">
          <!-- 显示图片标签 -->
          <img :class="{disabled:tag.disabled,selected:tag.selected}" @click='toggle(tag, item.values)' v-if="tag.picture" :src=tag.picture alt="">
          <!-- 显示文字标签 -->
          <span :class="{disabled:tag.disabled,selected:tag.selected}" @click='toggle(tag, item.values)' v-else>{{tag.name}}</span>
        </template>
      </dd>
    </dl>
  </div>
</template>
<script>
import powerSet from '@/vendor/power-set.js'
const spliter = '#'

// 获取选中的规格
const useSelectedSpecs = (specs) => {
  const result = []
  specs.forEach((item, index) => {
    // 获取每一种规格选中的对象
    const current = item.values.find(tag => tag.selected)
    if (current) {
      // 该规格选中了，放到数组的指定位置
      result[index] = current.name
    } else {
      // 该规格没有选中，默认填充undefined
      result[index] = undefined
    }
  })
  return result
}

// 封装一个函数： 生成路径字典
const usePathMap = (skus) => {
  const result = {}
  skus.forEach(sku => {
    console.log(sku)
    // 过滤无效的sku数据
    if (sku.inventory === 0) return
    // console.log(sku.specs)
    // 获取sku的规格集合， soecSet=[蓝色，中国，10cm]
    const specSets = sku.specs.map(item => item.valueName)
    // console.log(specSets)
    // 计算每一个集合的笛卡尔集(二维数组)
    const subSets = powerSet(specSets)
    // console.log(subSets)
    // 基于笛卡尔集生成路径字典
    // 需要把笛卡尔集中的每一项数据拼接为一个字符串作为key添加到路径字典中
    subSets.forEach(item => {
      // console.log(item)
      // 排除空集
      if (item.length === 0) return
      // 拼接路径的key:pathKey='蓝色#日本'
      const pathKey = item.join(spliter)
      // console.log(pathKey)
      if (result[pathKey]) {
        // 已经存在该key
        result[pathKey].push(sku.id)
        // console.log(result[pathKey])
      } else {
        // 尚不存在
        result[pathKey] = [sku.id]
      }
    })
  })
  return result
}

// 初始化的时候，判断每一个标签是否应该被禁用
// const initCheckSpecStatus = (specs, pathMap) => {
//   // 路径字典
//   // const pathMap = usePathMap(skus)
//   // 遍历每一个规格
//   specs.forEach(item => {
//     item.values.forEach(tag => {
//       // 判断规格是否在路径字典中存在，如果不存在就该被禁用
//       // 如果该规格不在路径字典中，添加一个属性disabled，值为true
//       tag.disabled = !pathMap[tag.name]
//     })
//   })
// }

// 点击任意规格时，判断按钮的状态（遍历所有的规格）
const clickCheckSpecStatus = (specs, pathMap) => {
  // 生成路径字典
  // const pathMap = usePathMap(skus)
  specs.forEach((item, i) => {
    // 遍历：颜色、产地、尺寸
    // selectedValues = [蓝色, undefined, 10cm]
    // 这里得到的值必须是点击选中的值
    const selectedValues = useSelectedSpecs(specs)
    item.values.forEach(tag => {
      if (tag.selected) {
        // 如果标签本身就是选中的，那么不需要判断禁用状态
        return
      } else {
        // 把没有选中的规格组合进去进行判断(判断所有规格的组合情况)
        selectedValues[i] = tag.name
      }

      // 过滤出有效值（选中的值）
      const validValues = selectedValues.filter(item => item)
      if (validValues.length > 0) {
        // 需要把选中的值组合成一个pathKey: 蓝色#10cm
        const pathKey = validValues.join(spliter)
        // 判断当前选中的值，是否在有效的路径字典中
        tag.disabled = !pathMap[pathKey]
      }
    })
  })
}

// 根据skuId控制规格的默认选中
const useDefaultSelectedSpec = (skuId, skus, spec) => {
  // skuId:要购买的商品的skuId
  // skus:表示后端返回的所有sku信息
  // spec:表示遍历出来的所有规格信息

  // 获取所有需要选中的规格 [蓝色，中国，30cm]
  const currentSku = skus.find(item => item.id === skuId)
  const targetSpec = currentSku.specs.map(item => item.valueName)
  // targetSpec = [蓝色，中国，30cm]
  // 遍历每一个规格标签，判断是否需要被选中
  spec.forEach(item => {
    item.values.forEach(tag => {
      // tag 中国/日本  黑色/蓝色 30cm/20cm/10cm
      if (targetSpec.includes(tag.name)) {
        tag.selected = true
      }
    })
  })
}

export default {
  name: 'GoodsSku',
  props: {
    skuId: {
      type: String,
      default: ''
    },
    specs: {
      type: Array,
      default: () => []
    },
    skus: {
      type: Array,
      default: () => []
    }
  },
  setup (props, { emit }) {
    // 测试路径字典
    const pathMap = usePathMap(props.skus)
    console.log(pathMap)

    // 控制根据skuId选中默认规格
    if (props.skuId) {
      useDefaultSelectedSpec(props.skuId, props.skus, props.specs)
    }

    // 初始化时，检测标签的状态
    // initCheckSpecStatus(props.specs, pathMap)
    // 初始化时，检测标签的状态
    clickCheckSpecStatus(props.specs, pathMap)

    // 渲染选中效果
    const toggle = (tag, list) => {
      // 把所有标签的选中都取消，只选中当前点击的标签
      list.forEach(item => {
        if (item !== tag) {
          // 排除当前点击标签，取消选中其他的标签
          item.selected = false
        }
      })
      // 当前点击标签单独控制
      tag.selected = !tag.selected

      // 获取选中的规格
      // const ret = useSelectedSpecs(props.specs)
      // console.log(ret)
      // [蓝色, undefined, 10cm]

      // 点击判断每个规格的禁用状态
      clickCheckSpecStatus(props.specs, pathMap)

      // 获取选中的规格相关的结果， skuId,价格，库存相关性信息
      // 判断是否所有的规格都选中了，
      const sv = useSelectedSpecs(props.specs)
      if (sv.every(item => item)) {
        // 规格都选择了，获取规格相关信息
        // 使用选中的规格拼接一个路径key
        const pathKey = sv.join(spliter)
        // 获取当前购买商品的skuId
        const skuId = pathMap[pathKey][0]
        // 根据skuId获取商品信息
        const info = props.skus.find(item => item.id === skuId)

        // 获取规格相关信息
        const skuInfo = {
          skuId: skuId,
          oldPrice: info.oldPrice,
          price: info.price,
          inventory: info.inventory,
          specText: ''
        }
        // 把信息传递给父组件
        emit('sku-info', skuInfo)
      } else {
        // 没有全部选中
        emit('sku-info', null)
      }
    }

    return { toggle }
  }
}
</script>
<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
